<?php
/**
 * 权限控制类，配合标准路由规则的。 单例模式
 * @author Hipop@126.com
 * 
 */

class Application_Service_Acl extends Zend_Acl{
	
	/**
	 * @var Application_Service_Acl
	 */
	private static $_instance = null; 

	/**
	 * 构造函数
	 */
	private function __construct(){		
		//构建资源
	  	$this->_buildResources();
	  	//构建角色
		$this->_buildRolesAndPrivileges();
		//绑定权限
		$this->_buildPrivaliges();
	}
	
	/**
	 * 阻止克隆
	 */
	private function __clone(){
		
	}
	
	/**
	 * 获取单例
	 * @return Application_Service_Acl
	 */
	public static function getInstance(){
		if(null == self::$_instance){
			//数据缓存
			$cache = Application_Service_Cache::getInstance();			
			$cacheid = "ACL_object";
			$arr = array();
			if(!($arr = $cache->load($cacheid))){
				$cacheObj = new self();
				$cache->save($cacheObj,$cacheid);
			}else{
				$cacheObj = $cache->load($cacheid);
			}
			self::$_instance = $cacheObj;
		}
		return self::$_instance;
	}
	
//	private function __construct($userBh = null,$company_id = null){
//		$this->getPrivilegeM() = new Application_Model_DbTable_Privilege();
		//加大内存，应该优化
		//ini_set("memory_limit","256M");
		//----------------------------------------------
//		$this->_buildResources();
//		$this->_buildRolesAndPrivileges($userBh, $company_id);
//		$this->_buildRoles();
//		$this->_buildRules($userBh,$company_id);
//	}
	/**
	 * 注册所有关注访问权限的资源
	 */
	private function _buildResources(){
		$privileges = $this->getPrivilegeM()->getAclPrivileges();
		foreach((array) $privileges as $k => $v) {
			$this->addResource($k);
		}
		/*$func = new Application_Model_DbTable_Func();
		//$resourceM = new Application_Model_DbTable_Privilege(); //Privilege这个名字~~!
		$funcarr = $func->getAllIdFcfullname();
		//$resources = $resourceM->fetchAll();
		foreach ((array)$funcarr as $id =>$fullname){
			$this->addResource(new Zend_Acl_Resource($id)); //注册资源，资源id
		}*/
	}
	
	/**
	 * 注册角色
	 * 只注册当前商家的角色
	 */
	private function _buildRoles(){
		$roleM = new Application_Model_DbTable_Role();
		$roles = $roleM->getByCompany();
		foreach((array)$roles as $role) {
			$this->addRole($this->getRoleId($role));
		}
		/*//$user = new Application_Model_DbTable_User();
		$roles = new Application_Model_DbTable_Role();
		//$userarr = $user->getAllUsers();
		$rolearr = $roles->getKVIdNameByCompany(); //这里返回id-name键值对
		foreach ((array)$rolearr as $id => $name){
			$this->addRole(new Zend_Acl_Role($id));
		}*/
	}
	
	
	
	/**
	 *	company——id和role_bh作为角色ID 
	 * @param array $role|int
	 */
	protected function getRoleId($role) {
//		if (!is_array($role)) {
//			$role = array(
//				'company_id' => $_SESSION['shoprr']['company_id'],
//				'id' => $role
//			);
//		}
		if (!is_array($role)) {
			$role = array('id' => $role, 'company_id' => $_SESSION['shoprr']['company_id']);
		} /*else {
//			//管理员们的数据记录，role_id是 id
//			if ($role['company_id'] == 0) $role['role_id'] = $role['id'];
		}
//		$role['company_id'] = $_SESSION['shoprr']['company_id'];
		//是role_id不是role_bh
*/		
		//注册角色时，用id；获取用户角色时，是role_id；系统设置的管理员呢，是role表中的
		//
		if ($role['role_id']) $role['id'] = $role['role_id'];
		return "{$role['company_id']}_{$role['id']}";
	}
	
	protected function _buildRolesAndPrivileges($userBh,$company_id) {
		if ($_SESSION['shoprr']['company_id']) {
			$roleM = $this->getPrivilegeM()->getRoleM();
			$roles = $roleM->getByCompany();
			$roles = (array) $roles;
			foreach($roles as $role) {
//				$this->addRole($this->getRoleId($role));
				$roleId = $this->getRoleId($role);
				if (!$this->hasRole($roleId)) $this->addRole($roleId);
			}
			
			foreach($roles as $role) {
				$roleId = $this->getRoleId($role);
				$privileges = $this->getPrivilegeM()->getRolePrivilegeM()->getByRoleBhCompanyId($role['id'], $role['company_id']);
	//			$keys = array_keys($privileges);
	//			$this->allow($roleId, $keys);
				foreach((array)$privileges as $key => $privilege) {
					if ($this->has($key)) $this->allow($roleId, $key);
				}
			}
		} else {
			
		}
	}
	
	/**
	 * 注册登录用户权限
	 */
	private function _buildRules($userBh,$company_id){
		/*$rolePrivilegeM = new Application_Model_DbTable_RolePrivilege();
		$rolePrivileges = $rolePrivilegeM->ge*/
		/*$rolePrivilege = new Application_Model_DbTable_RolePrivilege();
		//$arr = $privilege->getPrivilegeByUser($userBh,$company_id);
		$arr = $rolePrivilege->getActionRolesRulersByCompany();
		foreach ((array)$arr as $d){
			if($this->has($d['func_id']) && $this->hasRole($d['role_id'])){
				$this->allow($d['role_id'], $d['func_id'], $d['privilege_id']);
			}
		}*/
	}
	
	/**
	 * 判断是否有权限
	 * 
	 * @version 2.0
	 * 2.0的更改，将$role 的类型改为数组，可传入多个角色，只要有一个角色通过，即为通过
	 * @param string $module      模块名
	 * @param Array $role        角色(用户登录名)
	 * @param string $controller  控制器名
	 * @param string $action      动作名
	 */
	public function isMyAllow($module,$role,$controller,$action){
		foreach((array)$role as $role_id) {
			$key = $this->getPrivilegeM()->getKey($module, $controller, $action);
			if($this->isAllowed($this->getRoleId($role_id), $key)) return TRUE;
		}
		
		/*$privilege = new Application_Model_DbTable_Privilege();
		$arr = $privilege->getOnly($module,$controller,$action);
		$resource = $arr['func_id'];
		$action = $arr['action_id'];
		
	 	if (!is_array($role)) {
            $role = array($role);
        }
        foreach($role as $r){
        	if($this->isAllowed($r,$resource,$action))
        		return TRUE;
        }*/
		return FALSE;
	}
	
	/**
	 * 根据用户id 和资源id 判定
	 * @param int $userId
	 * @param int $resource 资源id 一般是privilege_id
	 */
	public function isUserResourceidAllowed($userId,$resourceid){
		$roles = $this->getPrivilegeM()->getUserRoleM()->getByUserId($userId);
		foreach((array)$roles as $role) {
			if($this->isRoleAllowed($role,$resourceid))
				return true;
		}
		return false;
	}
	
	/**
	 * 根据角色id 和资源id 判定
	 * @param int $roleid
	 * @param int $resource
	 */
	public function isRoleAllowed($roleid,$resourceid){
		$roleid = $this->getRoleId($roleid);
		$resourceid = intval($resourceid);
		$resource = $this->getPrivilegeM()->getAllMcastr();		
		$resource = $resource[$resourceid];
		if ($this->hasRole($roleid) && $this->isAllowed($roleid, $resource)) return true;
		return false;
	}
	/**
	 * 判断指定用户是否有权限访问某个m/c/a
	 * 
	 * @param int $userId
	 * @param string|null $action
	 * @param string|null $controller
	 * @param string|null $module
	 */
	public function isUserAllowed($userId = -1, $action = null, $controller = null, $module = null) {
		//如果是系统管理员，没有角色，直接返回true
		if ($_SESSION['shoprr']['admin_id'] == 25 && $_SESSION['shoprr']['company_id'] === "0") return true;
		if ($userId === -1) $userId = $_SESSION['shoprr']['admin_bh'];
		$request = Zend_Controller_Front::getInstance()->getRequest();
		if (!$action) $action = $request->getActionName();
		if (!$controller) $controller = $request->getControllerName();
		if (!$module) $module = $request->getModuleName();
		$resource = $this->getPrivilegeM()->getKey($module, $controller, $action);
		if ($userId) {
			//$user = $this->getPrivilegeM()->getUserM()->getByUserId($userId);
			//这儿不包含商家创建时的管理员角色
			$roles = $this->getPrivilegeM()->getUserRoleM()->getByUserId($userId);
			foreach((array)$roles as $role) {
				$roleId = $this->getRoleId($role);
//				$resource = $this->getPrivilegeM()->getKey($module, $controller, $action);
				if ($this->hasRole($roleId) && $this->isAllowed($roleId, $resource)) return true;
			}
		} else {//未登录的这样判断
			return $this->isAllowed(null, $resource);
		}
		
//		if ($user['is_admin']) {
//			
//		}
		return false;
	}
	
	/**
	 * 判断指定用户是否有权限访问某个m/c/a
	 * 
	 * @param int $userId
	 * @param string|null $action
	 * @param string|null $controller
	 * @param string|null $module
	 */
	
	public static function isUserAllowedS($userId = -1, $action = null, $controller = null, $module = null) {
		return self::getInstance()->isUserAllowed($userId, $action, $controller, $module);
	}
	
	public function isAllowed($role = null, $resource = null, $privilege = null) {
		$privileges = $this->getPrivilegeM()->getAclPrivileges();
		$key;
		if (is_string($resource)) $key = $resource;
		if ($resource instanceof Zend_Acl_Resource_Interface) {
			$key = $resource->getResourceId();
		}
		//检查，是不是匹配系统权限 如果不是系统管理员，禁止访问
//		if ($this->isSystemAdmin($role)) return true;
//		else {
//			foreach($this->systemPrivileges as $v) {
//				if (preg_match($v, $key)) return false;
//			}
//		}
		
		if ($key && !$privileges[$key]) return true;
		return parent::isAllowed($role, $resource, $privilege);
	}
	
	protected function isSystemAdmin($role) {
		return $_SESSION['shoprr']['admin_id'] == 25;
		return false;
	}
	
	/**
	 * 
	 * @return Application_Model_DbTable_Privilege
	 */
	public function getPrivilegeM() {
		return Application_Model_DbTable_Base::getInstance()->getPrivilegeM();
	}
}